Many modern applications make use of data item driven processing in which the arrival of a data item triggers work to be carried out as a result of processing of the data item. For example, this may be done by putting a message into a Java™ Message Service (JMS) queue which then causes a message-driven bean (MDB) to be invoked to process the message. Note that a message is typically taken off the queue and processed within the scope of a transaction, for example an XA transaction, and the messaging service registers a resource as a participant in the transaction such that it is directed to roll back if the transaction fails. This enables the messaging service to replace a message onto the message queue for reprocessing if the transaction which processed the message fails. Further, processing of a message may involve transactional work carried out by one or more other transactional resources which also register as participants in the transaction. For example, such a resource may represent an update to a database made as part of message processing. Now if the transaction fails, each of the registered participants is directed to roll back so that the message is replaced on the queue, and updates to databases made by the other resources are removed such that all transactional work done by the failed transaction is undone. Note that typically transactions do not provide any ordering for the various enlisted resources and, as a result, the resources may be directed to roll back in any order. (Java and all Java based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both).
Further, processing of a message may involve non-transactional work carried out by non-transactional resources, for example sending an e-mail or updating a resource, such as a flat file, which is not transaction-aware (i.e.: cannot register as a participant in the transaction). As a result, it may be desirable to perform one or more actions to compensate (logically undo) such work if the transaction fails. For example, this enables some consistency to be maintained between the transactional and non-transactional resources. For this purpose a compensation service may be used which initiates compensation if a transaction fails. To make use of a compensation service an application is written which includes a transaction to be run to process a message and associated compensation actions to be run if the transaction fails. In this way the compensation action(s) may be written to compensate correctly for non-transactional work done in the transaction. Now in the event the transaction fails when processing a message, after each of the transactional resources have been directed to rollback, the compensation service is invoked to run the compensation actions. Such actions could, for example, reverse an action (e.g.: by removing a record that was added to a file) or take alternative action (e.g.: by sending an additional e-mail to cancel the effects of a first e-mail), for an action taken by non-transactional work of the transaction.
However, when running a transaction which involves the processing of a message and compensation, if the transaction fails the message service is directed to roll back as part of transaction processing, whereas the compensation service is triggered as part of transaction completion. This means that the message is replaced onto the message queue before compensation is started, which leads to a timing problem because the message may be reprocessed on a different thread, or in a different process, before compensation of the non-recoverable resources has completed. For example this could result in the transaction which reprocesses the message working on uncompensated non-transactional data from the first transaction, for example in a flat file, which may result in it using invalid data and as a result working incorrectly and/or subsequently failing. Alternatively, for example, it could result in the transaction which reprocesses the message sending a second confirmation e-mail before a failure e-mail is sent as part of compensation of the first transaction.